﻿using System.Collections.Generic;
using Contrib.FeedsAggregator.Models;
using Contrib.FeedsAggregator.Services;
using Contrib.FeedsAggregator.ViewModels;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.DisplayManagement;
using Orchard.Localization;
using System.Linq;

namespace Contrib.FeedsAggregator.Drivers {
    public class FeedsAggregatorPartDriver : ContentPartDriver<FeedsAggregatorPart> {
        private readonly IFeedsService _feedsService;
        private readonly dynamic _shapeFactory;
        private readonly IContentManager _contentManager;

        public FeedsAggregatorPartDriver(IFeedsService feedsService, IShapeFactory shapeFactory, IContentManager contentManager) {
            _feedsService = feedsService;
            _shapeFactory = shapeFactory;
            _contentManager = contentManager;

            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        protected override DriverResult Display(FeedsAggregatorPart feedsAggregatorPart, string displayType, dynamic shapeHelper) {
            if (displayType != "Detail")
                return null;

            var list = _shapeFactory.List();
            list.AddRange(_feedsService.GetFeeds(feedsAggregatorPart.Id)
                .Select(feedPart => _contentManager.BuildDisplay(feedPart, displayType)));

            return ContentShape(shapeHelper.Parts_FeedsAggregator_FeedsAggregatorPart(Feeds: list));
        }

        protected DriverResult Editor(FeedsAggregatorPartViewModel feedsAggregatorPartViewPartViewModel, dynamic shapeHelper) {
            var results = new List<DriverResult> {
                ContentShape("Parts_FeedsAggregator_FeedsAggregatorPart",
                             () => shapeHelper.EditorTemplate(TemplateName: "Parts.FeedsAggregator.FeedsAggregatorPart", Model: feedsAggregatorPartViewPartViewModel, Prefix: Prefix))
            };

            if (feedsAggregatorPartViewPartViewModel.FeedsAggregatorPart.Id > 0) {
                _feedsService.UpdateFeedsForFeedsAggregator(feedsAggregatorPartViewPartViewModel.FeedsAggregatorPart, feedsAggregatorPartViewPartViewModel.Feeds);

                // Perform an initial update on the news
                foreach (FeedPartRecord feedPart in feedsAggregatorPartViewPartViewModel.FeedsAggregatorPart.Feeds) {
                    _feedsService.UpdateFeed(feedPart.Id);
                }
            }

            return Combined(results.ToArray());
        }

        protected override DriverResult Editor(FeedsAggregatorPart feedsAggregatorPart, dynamic shapeHelper) {
            FeedsAggregatorPartViewModel model = BuildEditorViewModel(feedsAggregatorPart);
            return Editor(model, shapeHelper);
        }

        protected override DriverResult Editor(FeedsAggregatorPart feedsAggregatorPart, IUpdateModel updater, dynamic shapeHelper) {
            FeedsAggregatorPartViewModel model = BuildEditorViewModel(feedsAggregatorPart);
            updater.TryUpdateModel(model, Prefix, null, null);
            return Editor(model, shapeHelper);
        }

        private FeedsAggregatorPartViewModel BuildEditorViewModel(FeedsAggregatorPart feedsAggregatorPart) {
            ILookup<int, FeedPartRecord> feedsAggregatorPartFeeds = feedsAggregatorPart.Feeds.ToLookup(feed => feed.Id);

            return new FeedsAggregatorPartViewModel {
                FeedsAggregatorPart = feedsAggregatorPart,
                Feeds = _feedsService.GetFeeds().Select(feedPart =>
                    new FeedPartViewModel(feedPart, feedsAggregatorPartFeeds.Contains(feedPart.Record.Id))).ToList()
            };
        }
    }
}